2019_cage_imaginary_landscape_4.py

#

SPDX-FileCopyrightText: 2019 Arnaud Froment & Thomas Paquot SPDX-FileCopyrightText: 2024 AlICe laboratory https://alicelab.be

SPDX-License-Identifier: GPL-3.0-or-later

#

-- coding:Utf8 --

#

Imaginary Landscape Nr.4 - John Cage # Authors: Arnaud Froment & Thomas Paquot # Date: 24/01/2020 # Blender version: 2.80 # OS: MacOS Catalina & Windows 10 #

#

import of the external functions

import bpy
import random
from math import pi
#

activation of boolean tools in blender settings

import addon_utils

addon_utils.enable("object_boolean_tools")
#
#

delete neg cube at every run

def reset():
    bpy.ops.object.select_all(action="DESELECT")
    bpy.data.objects["negative"].select_set(True)
    bpy.ops.object.delete()


PARAMETERS = {"scale_min": 10, "scale_max": 25, "patterns": 6, "radios": 12}
COIN_TOSSES = {"heads": 0, "tails": 0}
OBJECTS = {
    "cubes": [0, 0],
    "tetrahedrons": [0, 0],
    "icosahedrons": [0, 0],
}  # index 0 = build; index 1 = unbuild
#

Coin toss 3 times print(“You flipped heads”, total_heads, “times”,”and tails”, total_tails, “times”)

def cointoss():
    total_heads = 0
    total_tails = 0
    for _ in range(3):  # Coin toss 3 times to create a line 0 or 1 see futher down
        coin = random.randint(1, 2)
        if coin == 1:  # heads
            total_heads += 1
        elif coin == 2:  # tails
            total_tails += 1
#
    if (total_heads == 3 and total_tails == 0) or (
        total_heads == 2 and total_tails == 1
    ):
        hexlist.append(0)  # adds a 0 to hexlist
        print("🀰🀰🀰🀰    🀰🀰🀰🀰")  # Line print if 0
    elif (total_heads == 1 and total_tails == 2) or (
        total_heads == 0 and total_tails == 3
    ):
        hexlist.append(1)  # adds a 1 to hexlist
        print("🀰🀰🀰🀰🀰🀰🀰🀰🀰🀰🀰🀰")  # line print if 1

    COIN_TOSSES["heads"] += total_heads
    COIN_TOSSES["tails"] += total_tails
#

empty hexagram

hexlist = []
#

clear the hexagram and load it again

def hexagram():
    hexlist.clear()
    for _ in range(6):  # 6 x 3 coin tosses for an hexagram to be created
        cointoss()
#

print(hexlist,’\n’)

    print()
#

iChing List of 64 Hexagrams

ichinglist = [
    [1, 1, 1, 1, 1, 1],
    [0, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0],
    [0, 1, 0, 1, 1, 1],
    [1, 1, 1, 0, 1, 0],
    [0, 0, 0, 0, 1, 0],
    [0, 1, 0, 0, 0, 0],
    [1, 1, 0, 1, 1, 1],
    [1, 1, 1, 0, 1, 1],
    [0, 0, 0, 1, 1, 1],
    [1, 1, 1, 0, 0, 0],
    [1, 1, 1, 1, 0, 1],
    [1, 0, 1, 1, 1, 1],
    [0, 0, 0, 1, 0, 0],
    [0, 0, 1, 0, 0, 0],
    [0, 1, 1, 0, 0, 1],
    [1, 0, 0, 1, 1, 0],
    [0, 0, 0, 0, 1, 1],
    [1, 1, 0, 0, 0, 0],
    [1, 0, 1, 0, 0, 1],
    [1, 0, 0, 1, 0, 1],
    [1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1],
    [1, 1, 1, 0, 0, 1],
    [1, 0, 0, 1, 1, 1],
    [1, 0, 0, 0, 0, 1],
    [0, 1, 1, 1, 1, 0],
    [0, 1, 0, 0, 1, 0],
    [1, 0, 1, 1, 0, 1],
    [0, 1, 1, 1, 0, 0],
    [0, 0, 1, 1, 1, 0],
    [1, 1, 1, 1, 0, 0],
    [0, 0, 1, 1, 1, 1],
    [0, 0, 0, 1, 0, 1],
    [1, 0, 1, 0, 0, 0],
    [1, 1, 0, 1, 0, 1],
    [1, 0, 1, 0, 1, 1],
    [0, 1, 0, 1, 0, 0],
    [0, 0, 1, 0, 1, 0],
    [1, 0, 0, 0, 1, 1],
    [1, 1, 0, 0, 0, 1],
    [0, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 0],
    [0, 1, 1, 0, 0, 0],
    [0, 0, 0, 1, 1, 0],
    [0, 1, 1, 0, 1, 0],
    [0, 1, 0, 1, 1, 0],
    [0, 1, 1, 1, 0, 1],
    [1, 0, 1, 1, 1, 0],
    [0, 0, 1, 0, 0, 1],
    [1, 0, 0, 1, 0, 0],
    [1, 1, 0, 1, 0, 0],
    [0, 0, 1, 0, 1, 1],
    [0, 0, 1, 1, 0, 1],
    [1, 0, 1, 1, 0, 0],
    [1, 1, 0, 1, 1, 0],
    [0, 1, 1, 0, 1, 1],
    [1, 1, 0, 0, 1, 0],
    [0, 1, 0, 0, 1, 1],
    [1, 1, 0, 0, 1, 1],
    [0, 0, 1, 1, 0, 0],
    [0, 1, 0, 1, 0, 1],
    [1, 0, 1, 0, 1, 0],
]
#

Defines the parameters (64 values per parameters = I CHING) at each structural point (random)

def make_random():
    hexagram()
    x = (
        ichinglist.index(hexlist) + 1
    )  # Duration X, #indexing where in the list + 1 the hexagram is situated to randomize a number
    hexagram()
    y = ichinglist.index(hexlist) + 1  # Dynamic Y
    hexagram()
    z = ichinglist.index(hexlist) + 1  # Frequency Z
    hexagram()
    s = ichinglist.index(hexlist) + 1  # Scale
    hexagram()
    r = (
        ichinglist.index(hexlist) + 1
    ) * 5.625  # Rotation, #5.625 is the amount of times 64 can fit in 360
#

print(x,y,z,s,r)

    axis = random.choice(["x", "y", "z"])
    if eval(axis) % 2 != 0:  # Uneven elements are 0
        if axis == "x":
            x = 0
        elif axis == "y":
            y = 0
        elif axis == "z":
            z = 0

    if s not in range(
        PARAMETERS["scale_min"], PARAMETERS["scale_max"]
    ):  # Choose a range in the 64 elements
        s = 0

    return x, y, z, s, r  # Giving the info back to the make_random function when called
#

define the keywords of the basic forms

addcube = bpy.ops.mesh.primitive_cube_add
addtetrahedron = bpy.ops.mesh.primitive_cone_add
addicosahedron = bpy.ops.mesh.primitive_ico_sphere_add
#

Define the pattern

#
def pattern(loop):  # builds objects if no 0 in iching
    for _ in range(loop):
        x, y, z, s, r = (
            make_random()
        )  ##section for the cube, 8 vertices #return the x y z s r values
        if 0 not in {x, y, z, s, r}:  # if value is 0
            addcube(
                size=s,
                location=(x, y, z),
                rotation=((r * pi / 180), (r * pi / 180), (r * pi / 180)),
            )
            OBJECTS["cubes"][0] += 1
        else:
            pass  # counter
            OBJECTS["cubes"][1] += 1

        x, y, z, s, r = make_random()  # section for the tetrahedron, 4 vertices
        if 0 not in {x, y, z, s, r}:
            addtetrahedron(
                radius1=s,
                radius2=0,
                depth=s * 2,
                vertices=3,
                location=(x, y, z),
                rotation=((r * pi / 180), (r * pi / 180), (r * pi / 180)),
            )
            OBJECTS["tetrahedrons"][0] += 1
        else:
            pass
            OBJECTS["tetrahedrons"][1] += 1

        x, y, z, s, r = make_random()  # section for the icosahedron, 12 vertices
        if 0 not in {x, y, z, s, r}:
            addicosahedron(
                subdivisions=1,
                radius=s,
                location=(x, y, z),
                rotation=((r * pi / 180), (r * pi / 180), (r * pi / 180)),
            )
            OBJECTS["icosahedrons"][0] += 1
        else:
            pass
            OBJECTS["icosahedrons"][1] += 1
#

how much radios are chosen

def radio(loop):
    for _ in range(loop):
        pattern(PARAMETERS["patterns"])
#

call a new score

def score():
    radio(PARAMETERS["radios"])
#

shows info of the score created

def scoreinfo():
    print("Total coin tosses:", COIN_TOSSES["heads"] + COIN_TOSSES["tails"])
    print()
    print("Total build cubes:", OBJECTS["cubes"][0])
    print("Total unbuild cubes:", OBJECTS["cubes"][1])
    print()
    print("Total build tetrahedrons:", OBJECTS["tetrahedrons"][0])
    print("Total unbuild tetrahedrons:", OBJECTS["tetrahedrons"][1])
    print()
    print("Total build icosahedrons:", OBJECTS["icosahedrons"][0])
    print("Total unbuild icosahedrons:", OBJECTS["icosahedrons"][1])
    print()
    print("---------------------------")
#

Union off all the events

def union():
    bpy.ops.object.select_all(action="SELECT")
    bpy.ops.object.booltool_auto_union()
#

Name the Unified object ‘Positive’

#
def positive():
    bpy.ops.object.select_all(action="SELECT")
    bpy.context.object.name = "positive"
#

Add the cube of 64 to 64 to create the negative afterwards

#
def negative():
    addcube(size=64, location=(32, 32, 32))
    bpy.context.object.name = "negative"
    negative = bpy.context.object
#

Boolean operation: negative(cube) - positive (objects)

def boolnegpos():
    bpy.ops.object.modifier_add(type="BOOLEAN")
    bpy.context.object.modifiers["Boolean"].operation = "DIFFERENCE"
    bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["positive"]
    bpy.ops.object.modifier_apply(apply_as="DATA", modifier="Boolean")
#
def delpos():
    bpy.ops.object.select_all(action="DESELECT")
    bpy.data.objects["positive"].select_set(True)
    bpy.ops.object.delete()
#

rescale the final form to a 10x10 square

def rescale():
    bpy.ops.object.select_all(action="SELECT")
    bpy.ops.transform.resize(value=(0.15625, 0.15625, 0.15625))
    bpy.context.object.location[0] = 5
    bpy.context.object.location[1] = 5
    bpy.context.object.location[2] = 5
#

calling the functions:

reset()
score()
scoreinfo()
union()
positive()
negative()
boolnegpos()
delpos()
rescale()